package com.cashmama.market.api.domain.service;

import com.alibaba.fastjson.JSON;
import com.cashmama.market.api.infras.enums.PackageNameEnum;
import com.cashmama.market.api.domain.integration.AdvanceAiIntegrationService;
import com.cashmama.market.api.domain.utils.AppUtils;
import com.cashmama.market.api.domain.utils.MessageUtils;
import com.cashmama.market.api.domain.vo.RequestLocalInfo;
import com.cashmama.market.api.domain.vo.user.UserBriefDTO;
import com.cashmama.market.api.domain.vo.verifycode.VerifyCodeDTO;
import com.cashmama.market.api.infras.config.ApolloConfigUtil;
import com.cashmama.market.api.infras.consts.RedisKeyConsts;
import com.cashmama.market.api.infras.consts.TimeConsts;
import com.cashmama.market.api.infras.consts.VerifyCodeConsts;
import com.cashmama.market.api.infras.enums.message.VerifyCodeTypeEnum;
import com.cashmama.market.api.infras.utils.HttpUtils;
import com.cashmama.market.api.infras.utils.JzUtils;
import com.cashmama.market.api.infras.utils.StringUtils;
import com.fqgj.base.services.redis.RedisClient;
import com.fqgj.common.utils.RandomUtil;
import com.fqgj.exception.common.ApplicationException;
import com.qianli.cashmama.trade.common.enums.message.MessageSceneEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;

/**
 * @program: market-api
 * @description
 * @author: frank
 * @create: 2019-12-20 11:59
 **/
@Service
public class VerifyCodeService {

    private static final Logger LOGGER = LoggerFactory.getLogger(VerifyCodeService.class);

    @Autowired
    private ApiMessageService apiMessageService;
    @Autowired
    private AdvanceAiIntegrationService advanceAiIntegrationService;

    @Autowired
    private RedisClient redisClient;

    @Autowired
    private ApolloConfigUtil apolloConfigUtil;
    @Autowired
    private AppUtils appUtils;

    @Autowired
    private ApiUserCenterService apiUserCenterService;

    @Autowired
    private MessageUtils messageUtils;

    public void sendVerifyCode(VerifyCodeDTO verifyCodeDTO) {
        String type = verifyCodeDTO.getType();
        String mobile = verifyCodeDTO.getMobile();

//        //1 advance发送短信情况
//        if (VerifyCodeTypeEnum.VERIFY_TYPE_ADVANCE_IDENTITY_CHECK.equals(VerifyCodeTypeEnum.getEnumByName(type))) {
//            if (StringUtils.isEmpty(verifyCodeDTO.getUserCode())) {
//                throw new ApplicationException("need login to send OPT");
//            }
//            UserBriefDTO userBriefDTO = apiUserCenterService.getUserBriefInfoByUserCode(verifyCodeDTO.getUserCode());
//            advanceAiIntegrationService.aadhaarCheck(verifyCodeDTO.getUserCode(), mobile, userBriefDTO);
//            return;
//        }
        String redisVerifyCodeKey = redisKeyGenerator(type, mobile);
        //验证码先从缓存中获取 有的话就不要重新生成
        String redisVerifyCode = redisClient.get(redisVerifyCodeKey);
        String verifyCode = StringUtils.isEmpty(redisVerifyCode) ? RandomUtil.getVerifyCode(VerifyCodeConsts.VERIFY_CODE_LENGTH) : redisVerifyCode;

        LOGGER.info("== 发送验证码 ==,mobile:{}", mobile);
        if (apolloConfigUtil.isServerTest() || apolloConfigUtil.inWhiteList().contains(mobile)) {
            verifyCode = "123456";
        }

        LOGGER.info("sendVerifyCode,mobile:{},loginVerifyCode is {}", mobile, verifyCode);
        sendRegisterSms(mobile, verifyCode);
        redisClient.set(redisVerifyCodeKey, verifyCode, TimeConsts.FIVE_MINUTES);
    }

    private String redisKeyGenerator(String type, String mobile) {
        return RedisKeyConsts.VERIFY_CODE_REDIS_KEY_PREFIX + type + mobile;
    }


    private Boolean sendRegisterSms(String phone, String verifyCode) {
        if (apolloConfigUtil.isServerTest() || apolloConfigUtil.inWhiteList().contains(phone)) {
            LOGGER.info("==发送验证码拦截==");
            return true;
        }

        String smsProviderName = apolloConfigUtil.getSmsProviderName();
        LOGGER.info("== 发送验证码 ==,smsProviderName:{}", smsProviderName);
        if (smsProviderName.equalsIgnoreCase("gcarde")) {
            return sendRegisterSmsByGcarde(phone, verifyCode);
        } else if ("nx".equalsIgnoreCase(smsProviderName)) {
            return sendOTPByNx(phone, verifyCode);
        }

        return true;
    }

    private boolean sendOTPByNx(String phone, String verifyCode) {

        MultiValueMap<String, String> body = new LinkedMultiValueMap<String, String>();
        body.add("appkey", apolloConfigUtil.getNxSmsOtpAppKey());
        body.add("secretkey", apolloConfigUtil.getNxSmsOtpSecretKey());
        body.add("phone", "91" + phone);
        String packageName = RequestLocalInfo.getRequestBasicInfo().getPackageName();

        String appName = "RupeeMama";
        if (StringUtils.isEmpty(packageName)) {
            appName = "OTP";
        } else if ("com.kly.cm.mall".equalsIgnoreCase(packageName)) {
            appName = "CashMall";
        } else if ("in.cashmama.app".equalsIgnoreCase(packageName)) {
            appName = "CashMama";
        } else if ("com.vayloan.app".equalsIgnoreCase(packageName)) {
            appName = "LoanZone";
        }

        body.add("content", "[" + appName + "] " + verifyCode + " is your verification code, valid for 5 minutes, please do not disclose it to others. VASUKS");
        body.add("source_address", apolloConfigUtil.getNxSmsOtpSender());
        LOGGER.info("== nx 发送验证码 请求==,body:{}", JSON.toJSONString(body));
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(body, headers);

        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(apolloConfigUtil.getNxSmsUrl(), request, String.class);

        String res = responseEntity.getBody();
        LOGGER.info("== nx 发送验证码 结果==,res:{}", res);
        return true;
    }

    private boolean sendRegisterSmsByGcarde(String phone, String verifyCode) {
        String packageName = StringUtils.isEmpty(RequestLocalInfo.getRequestBasicInfo().getPackageName()) ? PackageNameEnum.DHANADHAN.getPackageName() : RequestLocalInfo.getRequestBasicInfo().getPackageName();
        String appName = appUtils.getAppVo().getAppName();

        //这里需要灵活配置，存在多个app的情况
        String template16 = JzUtils.toHexString("RMama Your OTP is " + verifyCode + ", Valid for 2 minutes.- GCARDE");
        String res = HttpUtils.doGet(
                apolloConfigUtil.getGcardeDomail() + "?spid=" + apolloConfigUtil.getGcardeAccount() + "&pwd=" + apolloConfigUtil.getGcardePassword() + "&das=0091" + phone + "&sm=" + template16,
                new HashMap<>(),
                new HashMap<>());

        LOGGER.info("== sendRegisterSmsByGcarde ==,res:{}", res);

        return true;
    }

    /**
     * 发送短信消息
     */
    private Boolean sendMsgSms(String phone, String verifyCode, Integer serviceType) {
        if (apolloConfigUtil.isServerTest() || apolloConfigUtil.inWhiteList().contains(phone)) {
            return true;
        }

        String bizCode = "";
        String packageName = StringUtils.isEmpty(RequestLocalInfo.getRequestBasicInfo().getPackageName()) ? PackageNameEnum.DHANADHAN.getPackageName() : RequestLocalInfo.getRequestBasicInfo().getPackageName();
        String appName = appUtils.getAppVo().getAppName();
        if (serviceType == VerifyCodeTypeEnum.VERIFY_TYPE_REGISTER.getType().intValue()) {//
            bizCode = messageUtils.getMessageBizCodeByPackageName(packageName, appName, MessageSceneEnum.SMS_REGISTER);
        } else if (serviceType == VerifyCodeTypeEnum.VERIFY_TYPE_LOGIN.getType().intValue()) {
            bizCode = messageUtils.getMessageBizCodeByPackageName(packageName, appName, MessageSceneEnum.SMS_LOGIN_WITH_OTP);
        } else if (serviceType == VerifyCodeTypeEnum.VERIFY_TYPE_FORGET_PASSWORD.getType().intValue()) {
            bizCode = messageUtils.getMessageBizCodeByPackageName(packageName, appName, MessageSceneEnum.SMS_FORGET_PASSWORD);
        } else if (serviceType == VerifyCodeTypeEnum.VERIFY_TYPE_UPDATE_PASSWORD.getType().intValue()) {
            bizCode = messageUtils.getMessageBizCodeByPackageName(packageName, appName, MessageSceneEnum.SMS_UPLOAD_PASSWORD);
        } else if (serviceType == VerifyCodeTypeEnum.VERIFY_TYPE_BIND_DEVICE.getType().intValue()) {
            bizCode = messageUtils.getMessageBizCodeByPackageName(packageName, appName, MessageSceneEnum.SMS_BIND_NEW_DEVICE);
        } else if (serviceType == VerifyCodeTypeEnum.VERIFY_TYPE_SELF_SIGN.getType().intValue()) {
            bizCode = messageUtils.getMessageBizCodeByPackageName(packageName, appName, MessageSceneEnum.SMS_SIGN_OTP);
        }

        return apiMessageService.sendMessage(phone, bizCode, verifyCode);
    }

}
